package com.jichaoyun.service.impl;

import com.alibaba.druid.support.json.JSONUtils;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.util.MapUtils;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jichaoyun.common.model.Result;
import com.jichaoyun.common.enums.MyExceptiontType;
import com.jichaoyun.common.ex.MyException;
import com.jichaoyun.common.utils.ExcelStyleUtils;
import com.jichaoyun.dao.mapper.UserMapper;
import com.jichaoyun.dao.mapper.ValveChangeMapper;
import com.jichaoyun.dao.mapper.ValveMapper;
import com.jichaoyun.model.entity.User;
import com.jichaoyun.model.entity.Valve;
import com.jichaoyun.model.entity.ValveChange;
import com.jichaoyun.model.vo.ValveComParametersVo;
import com.jichaoyun.service.ValveService;
import com.jichaoyun.service.util.TcpUtils.TcpConnect;
import com.jichaoyun.service.util.TcpUtils.TcpUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.Socket;
import java.net.URLEncoder;
import java.util.*;

/**
* @author ljc
* @description 针对表【valve】的数据库操作Service实现
* @createDate 2023-12-06 13:51:03
*/
@Service
public class ValveServiceImpl extends ServiceImpl<ValveMapper, Valve> implements ValveService{

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private ValveChangeMapper valveChangeMapper;

    /**
     * 新增阀门
     * @param valve
     * @return
     */
    @Override
    public Result<Object> addValve(Valve valve) {
//        System.out.println(valve.toString());

        Map<String,String> map = new HashMap<>();

        if(valve.getVName() == null){
            throw new MyException(MyExceptiontType.NOVALVENAME,null);
        }
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getUsername,valve.getUserName());
        User user = this.userMapper.selectOne(queryWrapper);
        if(user == null){
            throw new MyException(MyExceptiontType.USERNOTFIND,null);
        }
        LambdaQueryWrapper<Valve> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Valve::getVName,valve.getVName());
        Valve result = this.baseMapper.selectOne(wrapper);

        if (result != null) {
            throw new MyException(MyExceptiontType.DUPLICATEVALVERNAME,null);
        }

        this.baseMapper.insert(valve);
        return Result.success("增加阀门成功");
    }

    /**
     * 更改阀门信息
     * @param valve
     * @return
     */
    @Override
    public Result<Object>  updateValveInfo(Valve valve) {


        LambdaQueryWrapper<Valve> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Valve::getVName,valve.getVName());
        Valve result = this.baseMapper.selectOne(wrapper);

        if(result != null && !Objects.equals(result.getValveId(), valve.getValveId())){
            throw new MyException(MyExceptiontType.DUPLICATEVALVERNAME,null);
        }

        this.baseMapper.updateById(valve);
        return Result.success("更新成功");
    }

    /**
     * 获取阀门列表
     * @param pageNo
     * @param pageSize
     * @return
     */
    @Override
    public IPage<Valve> getValveList(Integer pageNo, Integer pageSize) {
        IPage<Valve> valveIPage = new Page<>(pageNo,pageSize);
        QueryWrapper<Valve> queryWrapper = new QueryWrapper<>();
        queryWrapper.orderByAsc("valve_id");

        return this.baseMapper.selectPage(valveIPage,queryWrapper);
    }


    @Override
    public IPage<ValveChange> selectAllValveChangeData(Integer pageNo, Integer pageSize) {
        IPage<ValveChange> valveIPage = new Page<>(pageNo,pageSize);
        QueryWrapper<ValveChange> queryWrapper = new QueryWrapper<>();
        queryWrapper.orderByAsc("id");

        return valveChangeMapper.selectPage(valveIPage,queryWrapper);
    }

    /**
     * 获取所有阀门名称
     * @return
     */
    @Override
    public List<String> getAllValveName() {
        List<String> nameList = new ArrayList<>();
        QueryWrapper<Valve> wrapper = new QueryWrapper<>();
        wrapper.select("v_name");
        List<Valve> valveList = this.baseMapper.selectList(wrapper);
        for(Valve item : valveList){
            nameList.add(item.getVName());
        }

        return nameList;
    }

    /**
     * 根据阀门名称获取阀门编号、阀门状态信息
     * @param valveName
     * @return
     */
    @Override
    public Map<String,Object> getValveInfoByName(String valveName) {
        Map<String,Object> map = new HashMap<>();

        LambdaQueryWrapper<Valve> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Valve::getVName,valveName);
        Valve valve = this.baseMapper.selectOne(queryWrapper);
        Socket socket = TcpConnect.clientInfoMapValve.get(valve.getValveId());
        TcpUtil tcpUtil = new TcpUtil();
        if(socket == null){
            throw new MyException(MyExceptiontType.VALVENOTCONNECT,null);
        }
        if(valve == null){
            throw new MyException(MyExceptiontType.VALVENOTFIND,null);
        }
        try{
            tcpUtil.readDataValve(socket.getOutputStream(), valve.getVAddress());
            Thread.sleep(1000);
        }catch (Exception e){
            e.printStackTrace();
        }

        map.put("阀门编号",valve.getValveId());
        map.put("阀门名称",valve.getVName());
        if(valve.getInputCurrent() >= 4){
            map.put("阀门开启状态",(int)((valve.getInputCurrent() - 4)/16 * 100));
        }else {
            map.put("阀门开启状态",0);
        }
        return map;
    }

    /**
     * 更改阀门开启程度
     * @param valveId
     * @param status
     * @return
     */
    @Override
    public Result<Object> updateValveStatusById(Integer valveId, byte status) throws IOException{

        Socket socket = TcpConnect.clientInfoMapValve.get(valveId);
        TcpUtil tcpUtil = new TcpUtil();

        Valve valve = this.getById(valveId);

        if(valve == null){
            throw new MyException(MyExceptiontType.VALVENOTFIND,null);
        }
        if(status > 100 || status < 0){
            throw new MyException(MyExceptiontType.DATAERROR,null);
        }

        try{
            tcpUtil.writeDataValve(socket.getOutputStream(), valve.getVAddress(),400 + (16 * status));
        }catch (Exception e){
            e.printStackTrace();
            return Result.fail("通讯失败，阀门未连接");
        }
//        valve.setVStatus(status);
//
//        this.baseMapper.updateById(valve);
        return Result.success("修改成功");
    }


    @Override
    public Result<Object> addValveChangeData(ValveChange valveChange) {
        valveChangeMapper.insert(valveChange);
        return Result.success("插入成功");
    }

    /**
     * 导出阀门信息数据到excel
     * @param response
     * @throws IOException
     */
    @Override
    public void getValveExcel(HttpServletResponse response) throws IOException {
        LambdaQueryWrapper<Valve> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.orderByAsc(Valve::getValveId);
        List<Valve> valveList = this.baseMapper.selectList(lambdaQueryWrapper);

        try {
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setCharacterEncoding("utf-8");
            // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
            String fileName = URLEncoder.encode("阀门信息表", "UTF-8").replaceAll("\\+", "%20");
            response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
            HorizontalCellStyleStrategy horizontalCellStyleStrategy = new HorizontalCellStyleStrategy(ExcelStyleUtils.getHeadStyle(), ExcelStyleUtils.getContentStyle());

            // 这里需要设置不关闭流
            EasyExcel.write(response.getOutputStream(), Valve.class)
                    .registerWriteHandler(horizontalCellStyleStrategy)
                    .autoCloseStream(Boolean.FALSE)
                    .sheet("sheet1")
                    .doWrite(valveList);

        } catch (Exception e) {
            // 重置response
            response.reset();
            response.setContentType("application/json");
            response.setCharacterEncoding("utf-8");
            Map<String, String> map = MapUtils.newHashMap();
            map.put("status", "failure");

            map.put("message", "下载文件失败" + e.getMessage());
            response.getWriter().println(JSONUtils.toJSONString(map));
            throw new MyException(MyExceptiontType.FILEDOWNLOADFAIL,"下载文件失败");
        }
    }

    /**
     * 修改站点通讯参数信息
     * @param comParameters
     */
    @Override
    public Result<Object>  updateComParameters(ValveComParametersVo comParameters) {
        UpdateWrapper<Valve> updateWrapper = new UpdateWrapper<>();
        updateWrapper.set("com_ip",comParameters.getComIp());
        updateWrapper.set("tcp_addr",comParameters.getTcpAddr());
        updateWrapper.set("udp_addr",comParameters.getUdpAddr());
        updateWrapper.set("collection_circle",comParameters.getCollectionCircle());
        updateWrapper.set("storage_circle",comParameters.getStorageCircle());
        updateWrapper.set("instruct_circle",comParameters.getInstructCircle());
        updateWrapper.set("tel",comParameters.getTel());

        this.baseMapper.update(null,updateWrapper);
        return Result.success("修改成功");

    }
}




